/*
    This class is an extension of the Frame class for use as the
    main window of an application.

    You can add controls or menus to ZEdit with Cafe Studio.
 */

package compiler;
import java.awt.Button;
import java.awt.Color;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.FileDialog;
import java.awt.Frame;
import java.awt.Label;
import java.awt.MenuItem;
import java.awt.Rectangle;
import java.io.IOException;
import java.io.RandomAccessFile;

public class MyCompiler extends Frame {
    public CPascalVirtualMachine machine = new CPascalVirtualMachine();
    public String objFileName;
    public CPascalCompiler compiler;
    public String path = "d:\\pascal";
    Label statusBar;
    public String clipBuffer;
    public String fileName = "noname.pas";

    public MyCompiler() {

	super("Mini Pascal Compiler -- noname.pas");

	//{{INIT_MENUS
		mb = new java.awt.MenuBar();

		fileMenu = new java.awt.Menu("&File");
		fileMenu.add("&New");
		fileMenu.add("&Open...");
		fileMenu.add("&Save");
		fileMenu.add("Save &As...");
		fileMenu.addSeparator();
		fileMenu.add("E&xit");
		mb.add(fileMenu);

		menu1 = new java.awt.Menu("&Edit");
		menu1.add("&Undo");
		menu1.addSeparator();
		menu1.add("Cu&t");
		menu1.add("Co&py");
		menu1.add("&Paste");
		menu1.add("&Delete");
		menu1.addSeparator();
		menu1.add("Select &All");
		mb.add(menu1);

		runMenu = new java.awt.Menu("&Run");
		runMenu.add("&Compile");
		runMenu.add("&Run");
		mb.add(runMenu);

		helpMenu = new java.awt.Menu("&Help");
		helpMenu.add("&About...");
		mb.add(helpMenu);
		setMenuBar(mb);
		//$$ mb.move(0,0);
		//}}

	compiler = new CPascalCompiler();

    setBackground(Color.lightGray);
	//{{INIT_CONTROLS
		setLayout(null);
		addNotify();
		resize(insets().left + insets().right + 442,insets().top + insets().bottom + 306);
		setTitle("Untitled");
		//}}
	editArea=new TextEditor(this, 20, 64);
	add("North",editArea);
	Dimension dim = editArea.preferredSize();
	statusBar = new Label("1:1");
	add("South", statusBar);
	editArea.resize(dim);
	editArea.move(0, 1);
	show();
	resize(dim.width + insets().left + insets().right, dim.height + insets().top + insets().bottom + 48);
	setResizable(false);
	editArea.requestFocus();
    show();
    }

    public synchronized void show() {
	move(50, 50);
	super.show();
    }

    public boolean keyUp(Event evt, int key)
    {
        boolean result = super.keyUp(evt, key);
        statusBar.setText(Integer.toString(editArea.cursorY) + ':' + Integer.toString(editArea.cursorX));
        return result;
    }

    public boolean handleEvent(Event event) {

    switch (event.id)
    {
	case Event.WINDOW_DESTROY:
	    hide();         // hide the Frame
	    dispose();      // tell windowing system to free resources
	    System.exit(0); // exit
	    return true;
	}
	return super.handleEvent(event);
    }

    public boolean action(Event event, Object arg) {
    String label;
	if (event.target instanceof MenuItem) {
	    label = (String) arg;
	    if (((String) arg).equalsIgnoreCase("&Run")) {
            selectedRun();
            return true;
        } else if (((String) arg).equalsIgnoreCase("&Compile")) {
            selectedCompile();
            return true;
        } else if (label.equalsIgnoreCase("&Newe")) {
	        selectedNew();
            return true;
	    } else if (label.equalsIgnoreCase("&Save")) {
	        selectedSave();
	        return true;
	    } else if (label.equalsIgnoreCase("&Delete")) {
	        selectedDelete();
	        return true;
	    } else if (label.equalsIgnoreCase("Select &All")) {
	        selectedSelectAll();
	        return true;
	    } else if (label.equalsIgnoreCase("&Paste")) {
	        selectedPaste();
	        return true;
	    } else if (label.equalsIgnoreCase("Co&py")) {
	        selectedCoPy();
	        return true;
	    } else if (label.equalsIgnoreCase("&Undo")) {
	        selectedUndo();
	        return true;
	    } else if (label.equalsIgnoreCase("Cu&t")) {
	        selectedCut();
	        return true;
	    } else if (label.equalsIgnoreCase("Save &As...")) {
	        selectedSaveAs();
	        return true;
	    } else if (label.equalsIgnoreCase("&About...")) {
		selectedAbout();
		return true;
	    } else if (label.equalsIgnoreCase("E&xit")) {
		selectedExit();
		return true;
	    } else if (label.equalsIgnoreCase("&Open...")) {
		selectedOpen();
		return true;
	    }
	}
	if (arg instanceof String) {
	    label = (String) arg;
	    if (label.equals("SaveNewFile"))
	    {
	        selectedSave();
	    }
	    editArea.setText("");
	    setTitle("Mini Pascal Compiler -- noname.pas");
	    return true;
	}
	return super.action(event, arg);
    }

    public static void main(String args[]) {
	new MyCompiler();
    }

    //{{DECLARE_MENUS
	java.awt.MenuBar mb;
	java.awt.Menu fileMenu;
	java.awt.Menu menu1;
	java.awt.Menu runMenu;
	java.awt.Menu helpMenu;
	//}}

    //{{DECLARE_CONTROLS
	//}}
    TextEditor editArea;
    public void selectedOpen() {
	    FileDialog dlg = new FileDialog(this, "Open...", FileDialog.LOAD);
	    //dlg.setFilenameFilter(new ZDialogFilter());
	    dlg.show();
	    path = dlg.getDirectory();
        fileName = dlg.getFile();
       	if (fileName.endsWith(".*.*"))
        {
            fileName = fileName.substring(0, fileName.length() - 4);
        }
        StringBuffer buffer = new StringBuffer(65536);
        byte[] byteBuf = new byte[65536];
        String str;
        int length;
        try
        {
            RandomAccessFile ifs = new RandomAccessFile(path + fileName, "r");
            length = ifs.read(byteBuf);
            ifs.close();
            editArea.setText(new String(byteBuf, 0, 0, length));
        }
        catch (IOException e)
        {
            Dialog errorDlg = new CIOErrorDlg(this, e.getMessage());
            errorDlg.show();
        }
        setTitle("Mini Pascal Compiler -- " + path + fileName);
    }
    public void selectedExit() {
	QuitBox theQuitBox;
	theQuitBox = new QuitBox(this);
	theQuitBox.show();
    }
    public void selectedAbout() {
	AboutBox theAboutBox;
	theAboutBox = new AboutBox(this);
	theAboutBox.show();
    }
    public void selectedSaveAs() {
        // to do: put event handler code here.
        FileDialog dlg = new FileDialog(this, "Save as...", FileDialog.LOAD);
	    dlg.setFilenameFilter(null);
	    dlg.show();
        path = dlg.getDirectory();
        fileName = dlg.getFile();
        if (fileName.endsWith(".*.*"))
        {
            fileName = fileName.substring(0, fileName.length() - 4);
        }

        RandomAccessFile dos = null;
        try
        {
            System.out.println(path );
            System.out.println(fileName);
            dos = new RandomAccessFile(path + fileName, "rw");
            dos.writeBytes(editArea.getText());
            dos.close();
            setTitle("Mini Pascal Compiler -- " + path + fileName);
        }
        catch (IOException e)
        {
            Dialog errorDlg = new CIOErrorDlg(this,e.getMessage());
            errorDlg.show();
        }
    }

    public void selectedCut() {
        // to do: put event handler code here.
        int ss = editArea.getSelectionStart();
        int se = editArea.getSelectionEnd();
        clipBuffer = editArea.getSelectedText();
        editArea.replaceText("",ss,se);
    }
    public void selectedUndo() {
        // to do: put event handler code here.

            }
    public void selectedCoPy() {
        // to do: put event handler code here.
        int ss = editArea.getSelectionStart();
        int se = editArea.getSelectionEnd();
        clipBuffer = editArea.getSelectedText();
    }
    public void selectedPaste() {
        // to do: put event handler code here.
        int ss = editArea.getSelectionStart();
        editArea.insertText(clipBuffer,ss);
    }
    public void selectedSelectAll() {
        // to do: put event handler code here.
       editArea.selectAll();
    }
    public void selectedDelete() {
        // to do: put event handler code here.
        int ss = editArea.getSelectionStart();
        int se = editArea.getSelectionEnd();
        editArea.replaceText("",ss,se);
    }
    public void selectedSave() {
        // to do: put event handler code here.
        RandomAccessFile dos = null;
        if (fileName.equals("noname.pas"))
            selectedSaveAs();
        else
        {
            try
            {
                dos = new RandomAccessFile(path + fileName, "rw");
                dos.writeBytes(editArea.getText());
                dos.close();
            }
            catch (IOException e)
            {
                Dialog errorDlg = new CIOErrorDlg(this,e.getMessage());
                errorDlg.show();
            }
        }
    }
    public void selectedNew() {
        // to do: put event handler code here.
        if (!(editArea.getText().equals("")))
        {
            selectedSave();
            //NewFileDlg dlg = new NewFileDlg(this);
            //dlg.show();
            editArea.setText("");
            setTitle("Mini Pascal Compiler -- noname.pas");
        }
    }
    public void selectedCompile() {
        // to do: put event handler code here.
       // if (fileName == null)
         //   return;
        selectedSave();
        objFileName = new String(fileName);
        objFileName = objFileName.substring(0,objFileName.indexOf((int)'.')) + ".exp";
        try
        {
            compiler.Compile(path + fileName,path + objFileName);
        }
        catch (IOException e)
        {
            Dialog errorDlg = new CIOErrorDlg(this,e.getMessage());
            errorDlg.show();
        }

    }
    public void selectedRun() {
        // to do: put event handler code here.
        try
        {
            int pos = fileName.indexOf((int)'.');
            if (objFileName == null)
            {
                objFileName = new String(fileName);
                objFileName = objFileName.substring(0,objFileName.indexOf((int)'.')) + ".exp";
                compiler.Compile(path + fileName,path + objFileName);
            }
            if (!fileName.regionMatches(true,0,objFileName,0,pos))
                compiler.Compile(path + fileName,path + objFileName);
            System.out.print("------------------" + path + fileName + "  Runing-------------------\n");
            machine.run(path + objFileName);
            machine.Reset();
            System.out.print("----------------------The End----------------------\n");
        }
        catch (IOException e)
        {
            Dialog errorDlg = new CIOErrorDlg(this,e.getMessage());
            errorDlg.show();
        }

    }
}


/*
    This class is a basic extension of the Dialog class.  It can be used
    by subclasses of Frame.  To use it, create a reference to the class,
    then instantiate an object of the class (pass 'this' in the constructor),
    and call the show() method.

    example:

    AboutBox theAboutBox;
    theAboutBox = new AboutBox(this);
    theAboutBox.show();

    You can add controls to AboutBox with Cafe Studio.
    (Menus can be added only to subclasses of Frame.)
 */

class AboutBox extends Dialog {

    public AboutBox(Frame parent) {

	    super(parent, "About", true);
	setResizable(false);

	//{{INIT_CONTROLS
	setLayout(null);
	addNotify();
	resize(insets().left + insets().right + 382, insets().top + insets().bottom + 128);
	label1=new Label("ZEdit for MiniPascal 1.0");
	add(label1);
	label1.reshape(insets().left + 16,insets().top + 22,232,20);
	OKButton=new Button("OK");
	add(OKButton);
	OKButton.reshape(insets().left + 272,insets().top + 48,96,32);
	Label2=new Label("written by ZChL");
	add(Label2);
	Label2.reshape(insets().left + 128,insets().top + 56,128,24);
	//}}
    }

    public synchronized void show() {
	Rectangle bounds = getParent().bounds();
	Rectangle abounds = bounds();

	move(bounds.x + (bounds.width - abounds.width)/ 2,
	     bounds.y + (bounds.height - abounds.height)/2);

	super.show();
    }

    public synchronized void wakeUp() {
	notify();
    }

    public boolean handleEvent(Event event) {
	if (event.id == Event.ACTION_EVENT && event.target == OKButton) {
		clickedOKButton();
		return true;
	}
	else

	if (event.id == Event.WINDOW_DESTROY) {
	    hide();
	    return true;
	}
	return super.handleEvent(event);
    }

    //{{DECLARE_CONTROLS
    Label label1;
    Button OKButton;
    Label Label2;
    //}}

    public void clickedOKButton() {
	handleEvent(new Event(this, Event.WINDOW_DESTROY, null));
    }
}


/*
    This class is a basic extension of the Dialog class.  It can be used
    by subclasses of Frame.  To use it, create a reference to the class,
    then instantiate an object of the class (pass 'this' in the constructor),
    and call the show() method.

    example:

    QuitBox theQuitBox;
    theQuitBox = new QuitBox(this);
    theQuitBox.show();

    You can add controls, but not menus, to QuitBox with Cafe Studio.
    (Menus can be added only to subclasses of Frame.)
 */

class QuitBox extends Dialog {

    public QuitBox(Frame parent) {

	super(parent, "Quit Application?", true);
	setResizable(false);

	//{{INIT_CONTROLS
	setLayout(null);
	addNotify();
	resize(insets().left + insets().right + 202, insets().top + insets().bottom + 128);
	yesButton=new Button("Yes");
	add(yesButton);
	yesButton.reshape(insets().left + 24,insets().top + 56,56,24);
	noButton=new Button("No");
	add(noButton);
	noButton.reshape(insets().left + 112,insets().top + 56,56,24);
	label1=new Label("Do you want to quit?");
	add(label1);
	label1.reshape(insets().left + 8,insets().top + 16,160,32);
	//}}
    }

    public synchronized void show() {
	Rectangle bounds = getParent().bounds();
	Rectangle abounds = bounds();

	move(bounds.x + (bounds.width - abounds.width)/ 2,
	     bounds.y + (bounds.height - abounds.height)/2);

	super.show();
    }

    public synchronized void wakeUp() {
	notify();
    }

    public boolean handleEvent(Event event) {
	if (event.id == Event.ACTION_EVENT && event.target == noButton) {
		clickedNoButton();
		return true;
	}
	else
	if (event.id == Event.ACTION_EVENT && event.target == yesButton) {
		clickedYesButton();
		return true;
	}
	else

	if (event.id == Event.WINDOW_DESTROY) {
	    hide();
	    return true;
	}
	return super.handleEvent(event);
    }

    //{{DECLARE_CONTROLS
    Button yesButton;
    Button noButton;
    Label label1;
    //}}

    public void clickedYesButton() {
	System.exit(0);
    }
    public void clickedNoButton() {
	handleEvent(new Event(this, Event.WINDOW_DESTROY, null));
    }
}
